iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0

簡介

在之前的 Requests 章節中,我們探討了軟體系統之間的頻繁溝通與互動。這些系統不僅能夠獲取來自其他系統的資料,還可以向它們發送請求以執行特定指令。而 Requests 套件則是處理 HTTP 傳輸協定時常用的工具之一。

對於 Test Code 而言,通常不希望在執行測試時實際與真實伺服器進行互動,這樣做可能會帶來以下幾個問題:

  1. 依賴外部服務的穩定性
    測試結果會依賴於外部 API 的狀態。如果外部服務暫時中斷或出現問題,測試便會失敗,讓開發者誤以為是自己的 Product Code 有錯誤。此外,正如前文所提到的 FreezeGun,若外部 API 的回應數據會隨時間變化,測試結果也將因此變得不可預期和無法重複。

  2. 消耗 API 配額,增加測試成本
    許多 API 都設有請求速率限制(rate limit)。如果每次測試都發送真實請求,則可能迅速達到配額上限,導致測試無法繼續進行。如果使用的 API 是付費服務,這將進一步增加測試的運行成本。

  3. 污染真實數據
    直接發送真實請求可能會影響外部系統的數據,例如創建不必要的條目、修改或刪除重要資料,甚至可能引發安全問題。

本文將介紹一個名為 Responses 的套件。當 Product Code 透過 Requests 套件發送請求時,Responses 套件會攔截這些請求,並根據 Test Code 事先準備的假資料進行回應,從而模擬實際發送請求並接收回覆的過程。接下來,我將通過具體的範例進行詳細說明。

範例

本次範例使用的是 Responses 0.25.3 版本

poetry add responses=0.25.3

首先,我們將準備一個 Product Code 函式,該函式會向貓咪網站發送請求。

import requests

API_URL = "https://catfact.ninja/fact"


def get_cat_fact() -> dict:
    response = requests.get(API_URL)
    response.raise_for_status()
    return response.json()

接著,我們可以使用 Responses 套件來攔截真實請求。只需在需要攔截的測試函式上方添加 @responses.activate Decorator,並創建要回傳的假資料。在本次測試中,我選擇模擬貓咪網站的回傳值為 cat is cute。因此,當執行到函式 get_cat_fact 中的 requests.get(API_URL) 時,獲得的 JSON 回覆將是 {"fact": "cat is cute"},這樣每次測試的結果都將保持一致。

import responses

@responses.activate
def test_get_cat_fact():
    # Arrange
    responses.add(responses.GET, API_URL, json={"fact": "cat is cute"}, status=200)

    # Act
    result = get_cat_fact()

    # Assert
    assert result == {"fact": "cat is cute"}

最後我們可以執行 poetry run pytest 即可看到測試的結果
https://ithelp.ithome.com.tw/upload/images/20241009/20168663TtV6JqKQYs.png


上一篇
[Day 25] Freezegun
下一篇
[Day 27] Flask Test Client
系列文
Python 不止於數據,開發應用程式它也在行!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言